package org.jmc.refmanager.web.wicket.page.validation;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow.MaskType;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.RequiredTextField;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.validation.validator.PatternValidator;
import org.jmc.refmanager.domain.model.Change;
import org.jmc.refmanager.domain.model.OrgUnit;
import org.jmc.refmanager.domain.model.User;
import org.jmc.refmanager.domain.service.ChangeManager;
import org.jmc.refmanager.domain.service.OrgUnitManager;
import org.jmc.refmanager.domain.service.UserManager;
import org.jmc.refmanager.domain.service.exception.BusinessException;
import org.jmc.refmanager.jsr303validators.JSR303FormValidator;
import org.jmc.refmanager.security.SecurityHelper;
import org.jmc.refmanager.web.wicket.form.ServiceNewForm;
import org.jmc.refmanager.web.wicket.page.panel.SelectCodePostalPanel2;
import org.jmc.refmanager.web.wicket.page.panel.SelectParentPanel1;
import org.jmc.refmanager.web.wicket.page.template.TemplatePage;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

/**
 */
public class TaskEditNewChangePage extends TemplatePage {
	@SpringBean(name="orgUnitManager")
	private OrgUnitManager orgUnitManager;

	@SpringBean(name="taskManager")
	private ChangeManager taskManager;
	
	@SpringBean(name="userManager")
	private UserManager userManager;

	/**
	 * @param parameters
	 */
	public TaskEditNewChangePage(PageParameters parameters) {
		super(parameters);
		initComponents(parameters);
	}

	private void initComponents(final PageParameters parameters) {
		add(new Label("pageTitle", "Validation du changement"));

		final String matricule = SecurityHelper.getAuthentication().getName();

		final Integer taskId = parameters.getAsInteger("id");
		final Change change = taskManager.findById(taskId);
		
		// Recuperer le change et le service
		OrgUnit editService = getNewService(change);
		final IModel<OrgUnit> serviceModel = new Model<OrgUnit>(editService);
		
		
		final RequiredTextField<String> codePostalTextField = new RequiredTextField<String>("codePostal", 
				new PropertyModel<String>(serviceModel, "codePostal"));
		codePostalTextField.setOutputMarkupId(true);
		codePostalTextField.add(new PatternValidator("[0-9]{5}"));

		final Label communeLabel = new Label("commune", 
				new PropertyModel<String>(serviceModel, "commune"));
		communeLabel.setOutputMarkupId(true);

		final ModalWindow codePostalPicker = buildCodePostalPicker();
		codePostalPicker.setContent(new SelectCodePostalPanel2(codePostalPicker.getContentId(), serviceModel) {
			private static final long serialVersionUID = 1L;

			@Override
			public void onSave(AjaxRequestTarget target) {
				target.addComponent(codePostalTextField);
				target.addComponent(communeLabel);
				codePostalPicker.close(target);
			}

			@Override
			public void onCancel(AjaxRequestTarget target) {
				codePostalPicker.close(target);
			}
		});

		// Gestion du picker de service parent
		final RequiredTextField<String> parentCodeUOTextField = new RequiredTextField<String>("parentCodeUO", 
				new PropertyModel<String>(serviceModel, "parent.codeUO"));
		parentCodeUOTextField.setOutputMarkupId(true);
		
		final ModalWindow parentCodeUOPicker = buildParentCodeUOPicker();
		parentCodeUOPicker.setContent(new SelectParentPanel1(parentCodeUOPicker.getContentId(), serviceModel) {
			private static final long serialVersionUID = 1L;

			@Override
			public void onSave(AjaxRequestTarget target) {
				target.addComponent(parentCodeUOTextField);
				parentCodeUOPicker.close(target);
			}
			
			@Override
			public void onCancel(AjaxRequestTarget target) {
				parentCodeUOPicker.close(target);
			}
		});
		
		// Formulaire d'edition de service
//        final ServiceEditForm editForm = new ServiceEditForm("validateForm", 
//        		new CompoundPropertyModel<OrgUnit>(serviceModel), 
//        		codePostalPicker, parentCodeUOPicker) {
//			private static final long serialVersionUID = 1L;
//        };
		final ServiceNewForm editForm = new ServiceNewForm("validateForm",
				new CompoundPropertyModel<OrgUnit>(serviceModel), codePostalPicker, parentCodeUOPicker);
        add(editForm);

		// Validateur JSR303
        editForm.add(new JSR303FormValidator());

        editForm.add(parentCodeUOPicker);
        editForm.add(codePostalPicker);

        Button btnApprove = new Button("btnApprove") {
        	private static final long serialVersionUID = 1L;

        	@Override
			public void onSubmit() {
        		try {
	        		OrgUnit service = editForm.getModelObject();
	
	        		// Appel de la couche de service
					User approver = userManager.getByMatricule(matricule);
					taskManager.commitAndApprove(change, service, true, approver);
	
					// Affiche le message sur la page redirigee
					getSession().info("Les modifications du service ont été approuvées avec succès.");
					setResponsePage(MyGroupTasksListPage.class);
				} catch (ConstraintViolationException e) {
					error("Les modifications n'ont pas été prises en compte.");
					Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
					for (ConstraintViolation<?> constraintViolation : violations) {
						error(constraintViolation.getMessage());
					}
					setResponsePage(TaskEditNewChangePage.this);
				} catch (BusinessException be) {
					error(be.getMessage());
					setResponsePage(TaskEditNewChangePage.this);
				}
        	}
        };
        editForm.add(btnApprove);

        Button btnReject = new Button("btnReject") {
        	private static final long serialVersionUID = 1L;

        	@Override
			public void onSubmit() {
        		// Appel de la couche de service
        		User approver = userManager.getByMatricule(matricule);
        		taskManager.commitAndReject(change, approver);
        		
				// Affiche le message sur la page redirigee
				getSession().info("Les modifications du service ont été rejetées avec succès.");
				setResponsePage(MyGroupTasksListPage.class);
			}
        };
        editForm.add(btnReject);

		Button btnCancel = new Button("btnCancel") {
			private static final long serialVersionUID = 1L;
			@Override
			public void onSubmit() {
				// Affiche le message sur la page redirigee
        		getSession().warn("Aucune modification n'a été réalisée");
				setResponsePage(MyGroupTasksListPage.class);
			}
		};
		// Pas de validation
		btnCancel.setDefaultFormProcessing(false);
		editForm.add(btnCancel);

		editForm.add(codePostalTextField);
		editForm.add(communeLabel);

		parentCodeUOTextField.setEnabled(false);
		editForm.add(parentCodeUOTextField);
	}

	/**
	 * 
	 * @param change
	 * @return
	 */
	private OrgUnit getNewService(Change change) {
		// Recupere l'objet contenant les changements
		String xmlChanges = change.getObject();

		Serializer serializer = new Persister();
		OrgUnit newService = null;
		try {
			newService = serializer.read(OrgUnit.class, xmlChanges);
		} catch (Exception e) {
			throw new IllegalStateException(
					"Impossible de desérialiser les changements", e);
		}

		// Recheche du service parent e partir de son identifiant
		// Cet identifiant ne change pas meme s'il a ete deplace.
		Integer parentId = newService.getParentId();
		OrgUnit parent = orgUnitManager.findById(parentId);
		newService.setParent(parent);
		
		return newService;
	}
	
	/**
	 * @return
	 */
	private ModalWindow buildCodePostalPicker() {
		final ModalWindow codePostalPicker = new ModalWindow("codePostalPicker");
		codePostalPicker.setInitialWidth(800);
		codePostalPicker.setWidthUnit("px");
		codePostalPicker.setUseInitialHeight(true);
		codePostalPicker.setHeightUnit("px");
		codePostalPicker.setResizable(true);
		codePostalPicker.setMaskType(MaskType.TRANSPARENT);
		return codePostalPicker;
	}

	/**
	 * @return
	 */
	private ModalWindow buildParentCodeUOPicker() {
		final ModalWindow parentCodeUOPicker = new ModalWindow("parentCodeUOPicker");
		parentCodeUOPicker.setInitialWidth(800);
		parentCodeUOPicker.setWidthUnit("px");
		parentCodeUOPicker.setUseInitialHeight(true);
		parentCodeUOPicker.setHeightUnit("px");
		parentCodeUOPicker.setResizable(true);
		parentCodeUOPicker.setMaskType(MaskType.TRANSPARENT);
		return parentCodeUOPicker;
	}

}

